Skip to content

feat: implement Beta.2.1 unified Router and standalone Element tooling - #1343

Draft
SisyphusZheng wants to merge 24 commits into
devfrom
codex/beta2-1-router-core
Draft

feat: implement Beta.2.1 unified Router and standalone Element tooling#1343
SisyphusZheng wants to merge 24 commits into
devfrom
codex/beta2-1-router-core

Conversation

@SisyphusZheng

@SisyphusZheng SisyphusZheng commented Sep 8, 2026

Copy link
Copy Markdown
Member

Beta.2.1: Router/core convergence, standalone Element, prerelease semantics

Target

Beta.2.1 implementation for #1320, #1323, #1324, #1325 and #1338, under ADR-0152 and
docs/current/VERSION_PLAN.md. This branch contains the approved planning content of
#1342 (still OPEN) through merge d16f7223 (planning SHA dcfa2ee5); per the
governance order, #1342 merges first, then this PR is refreshed onto the new dev.
The comparison includes that prerequisite plan until then.

Architecture

route declarations (explicit Route Mode + generated Framework Mode records)
        ↓
    RouteTable            ← one URL record chosen before method dispatch
        ↓
 URLPatternList           ← ordered first-match, value identity
        ↓
 RouteResolution          ← match / 405+Allow / not-found
     /       \
 Request    Navigation
  Hono    Navigation API   ← executors, never a second matcher
  • path is the only pathname truth; pattern (RoutePatternComponents) carries only
    non-pathname URL components and a runtime pathname is rejected, not silently honored.
  • Pathname captures and URLSearchParams stay separate; router.searchParams hands out
    per-reader snapshots so loaders/actions cannot mutate router state.
  • SSG discovers eligible static pages from canonical route records and renders through
    the real dispatcher. Browser navigation keeps POST/reload/fragment/download/cross-origin
    browser-owned; every mount gets a fresh AbortController; guard vetoes restore via a
    marked replace navigation that the router never re-intercepts.

What Changed

  • One RouteTable/RouteResolution for explicit and generated records; 405/Allow belongs
    to the URL winner; explicit HEAD wins, otherwise HEAD falls back to GET inside the
    winner with an empty body.
  • SSG page discovery moved from Hono's route list to canonical routeInfo projection
    (host routes preserved, wildcard excluded); the www build emits 150 static pages again.
  • Navigation ownership checks run before pending/intercept side effects; fresh execution
    signal per mount; stale loader/action/guard results never commit.
  • @openelement/adapter-vite/element exposes the existing private compiler plugin for
    standalone Element tooling; packed App/UI edges are optional peers.
  • Version tooling owns the full prerelease identifier chain
    (beta.2 → beta.2.1 → beta.2.2 → beta.2.3 → 1.0.0-alpha.1 by explicit product-stage
    transition); prereleaseNumber is documented as a legacy channel-level field.
  • CI/gates realigned with the architecture: cache-boundary gate slices the generated
    __pageHandlers method table (no-store assertions preserved, non-vacuous); www truth
    gates admit the approved planned version chain and quoted roadmap keys; the critical-path
    gate tracks the renamed path-param evidence; the supplemental AI-review job reports a
    missing/errored review as a warning instead of masquerading as green evidence
    (non-blocking per the 2026-09-09 maintainer decision).

What Was Removed

  • The pre-convergence RouteTable static-map/dynamic-list/sort/query-proxy split and the
    method-dependent winner fallback; the duplicate route.path declaration in generated
    records; the per-page Hono winner/405 paths; pattern.pathname as an override channel.
  • No second matcher, compiler or manifest truth was added anywhere.

Fork / Dependency Boundary

  • open-element/url-pattern-list @ 00bface02e3117222dea9c620a63792545f04c13 (on top of
    upstream v0.5.0 4911e649, history and MIT attribution preserved) carries the qualified
    implementation: 109/109 Node-native tests after a clean npm ci, ordered-linear-oracle
    differential coverage on native and polyfill constructors with seeded/reduced failures,
    and construction/hit/miss/memory benchmarks in its BENCHMARKS.md (GC-controlled,
    retained vs transient; static-only 5000-pattern hit 0.0057ms vs linear 2.82ms; the
    all-conservative scenario honestly degrades to linear). Two genuine upstream bugs have
    recipient-native reproductions drafted in the fork's docs/upstream-issues.md
    (unreported; upstream responsiveness is not an OE gate).
  • External blocker: publishing @open-element/url-pattern-list@0.6.0 to npm is a
    separate release authorization this task does not have. Until it lands, the embedded
    production copy at packages/app/src/internal/router/url-pattern-list/ remains the
    transitional matcher (its PROVENANCE.md records the fork as its maintenance home and
    retirement condition). Switch rehearsal: RouteTable ran the fork's packed 0.6.0 build
    through the route-resolution/router-http/client-router/route-pattern suites — 41/41 pass;
    the post-publish switch is a small, rehearsed diff (constructor entries → addPattern).
  • The fork contains no RouteRecord/HTTP/Hono/loader-action/renderer concepts.

Standalone Element

deno task consumer:packaged-element proves author → compile → pack → install outside the
workspace → plain HTML → real registration/attribute/event updates in Chromium 147,
Firefox 148 and WebKit 26.4, with no Router/App/UI installed, no workspace aliases, a clean
browser module graph, 32 reachable declaration modules checked, and authored source maps
retained. The compiler stays private; this is a tooling subpath, not a public compiler API.

Version Semantics

Lossless multi-identifier parsing/comparison; checkpoint succession is explicit
(nextCheckpointVersion), product-stage transition is explicit (1.0.0-alpha.1);
historical internal 0.44.0-alpha.0–10 stay unpublishable; channels map to dist-tags.
beta.3 ordering is legal SemVer but not an approved checkpoint (www truth gate rejects it).
No package version was bumped.

Validation — exact final SHA 95c30600

Local (macOS arm64, Deno 2.9.0 / Node 24.18.0; Chromium 147 / Firefox 148 / WebKit 26.4):

  • deno task test: 1920 passed (105 steps) + supabase starter 150 passed, 0 failed.
  • deno task build: full chain green; 150 static pages incl. /, /docs, sitemap.xml
    (146 URLs); artifact-truth and link checks pass.
  • deno fmt --check, deno lint, deno task typecheck, arch:check, graph:check,
    workflow:check, docs:truth, actions:check-pins: all pass.
  • Browser navigation: www/e2e chromium full 338 passed; firefox/webkit smoke
    171 + 171 passed; Deno-driven three-browser POST/fragment/reload and packed-Element
    proofs pass.
  • Consumers: consumer:packaged, consumer:packaged-ui, consumer:packaged-element pass
    against freshly packed tarballs.

CI on this exact SHA: autoflow-ci PASS (16m36s full matrix: build, coverage,
critical-paths, chromium/firefox/webkit e2e, request-time/ui-dogfood fixture gates,
starter smoke, static-output freeze, packed consumers)
, pr-full-ci-evidence PASS,
Cloudflare Pages PASS, dist/server Node 20 + Node 24 + Bun smoke PASS, CodeQL /
dependency-review / workspace-qualification / Analyze PASS. The supplemental review
job is green with a warning annotation (no review executed — see below).

Known Non-blocking External Conditions

Release Impact

None: no version bump, tag, npm publish, deployment, merge or issue closure. Examples stay
frozen. Release state and evidence files are unchanged; Beta.2.1 publication remains a
separately gated decision.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

@SisyphusZheng

Copy link
Copy Markdown
Member Author

Maintainer-approved Beta.2.x plan updated on 2026-09-08 in planning PR #1342, ADR-0152, VERSION_PLAN, 15 existing issues and Project 3.

The review comment #1343 (comment) says APIError: Insufficient Balance. The review workflow's SUCCESS is not a completed review. #1332 explicitly owns service recovery and failure propagation as an immediate merge prerequisite, not deferred cleanup. No provider/model or billing changes have been made.

#1343 remains incomplete: SSG output/navigation findings, fork migration/memory baselines, actual review, final-SHA CI and fresh verifier evidence are outstanding. Confirming #1342 ancestry is not a claim of baseline CI success. These planning updates do not repair product code or authorize release. Consume the updated #1342 planning contract before continuing implementation.

DevBot added 9 commits September 8, 2026 22:51
Consumes planning HEAD dcfa2ee. toSSG discovery via app.routes yields
nothing behind app.all('*', dispatcher) (middleware arity filtered);
project eligible static pages (rendering!=dynamic, non-dynamic) for
discovery only, render through real app.fetch/request. Preserve host
routes, exclude wildcard. Align default mock dispatcher with routeInfo.

Fixes RED ssg-render record test; www build 150 pages, /,/docs,sitemap present.
…oller

POST with formData leaves to browser/server before pending/intercept;
fragment-only and reload default browser-owned in history mode, hash
semantics separate. Each spa mount gets a fresh AbortController; stale
loader/action results never commit.

Tests: native ownership unit (POST/fragment/reload/GET), mount fresh
signal (mount/dispose/remount, direct remount stale, action signal),
3-browser POST/fragment/reload proof + existing nav regression.
The ADR-0152 chain (beta.2.1-beta.2.3, then 1.0.0-alpha.1) is planned, not
retired: derive exemptions from lib/version.ts checkpoint/stage successors
instead of banning every non-current prerelease. Unapproved prereleases
(beta.3, historical 0.44.0-alpha.N) stay forbidden; the alpha.N shorthand
no longer matches inside an exempted full version. Fixes the www build
artifact-truth failure introduced by consuming planning HEAD dcfa2ee.
The review action posts provider errors as PR comments while exiting 0, so
the green wrapper was not review evidence (observed on #1343: APIError
Insufficient Balance). A Deno gate now verifies the step outcome and the
run-attributed review comment, matching structural provider/API error
signatures across billing, rate-limit, auth, availability, timeout and model
categories; absence of evidence fails closed. Provider restoration itself
needs external billing action and stays a merge prerequisite.
…patch

fullstack:boundary-check sliced per-route app.get/app.post registrations;
the unified dispatcher keeps per-record handlers in the generated
__pageHandlers method table. Slice that table instead, preserving the
ADR-0121 no-store assertions (non-vacuous GET presence, baseline emission,
public-cache rejection). Drop the duplicate route.path from the file-routed
configuration examples: file paths own generated route paths (ADR-0152).
Wire the standalone Element packed-consumer proof as a deno task.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 9, 2026

Copy link
Copy Markdown

Deploying openelement with  Cloudflare Pages  Cloudflare Pages

Latest commit: 95c3060
Status: ✅  Deploy successful!
Preview URL: https://94764ac4.lessjs.pages.dev
Branch Preview URL: https://codex-beta2-1-router-core.lessjs.pages.dev

View logs

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

The planning rewrite of roadmap.tsx quotes object keys ('stamp': …); the
AST extractor only accepted identifiers, so no CURRENT entry was found.
Accept string-literal keys as well.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

open-element/url-pattern-list @00bface carries the qualified implementation,
Node-native differential tests and the four construction/hit/miss/memory
benchmarks. The embedded copy remains the production matcher until the
separately authorized npm publish unblocks consumption (#1324).
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

…ion API

history.replaceState fires a navigate event (navigationType replace) when
the Navigation API is active; the router intercepted its own guard-veto
restore as a fresh navigation and emitted a spurious change notification
after a blocked back/forward walk (3-browser router-guard e2e failure).
Mark the restore's replace navigation and intercept it without
rematch/notify; an unintercepted marked replace races the in-flight
traverse and never lands. The e2e probe now observes Navigation API
navigations (navigation.navigate/updateCurrentEntry replace reporting),
which the legacy history.pushState/replaceState spies cannot see.

Also: point the critical-path gate at the renamed path-param decoding
evidence, and regenerate the content graph after the guide edits.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

The review job is supplemental and must not block CI. The outcome gate
still detects a non-executed or provider-errored review (step outcome plus
run-attributed comment classification) and surfaces it as a warning
annotation instead of a red check — visible, never silently counted as
review evidence.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

DevBot added 4 commits September 9, 2026 10:43
pattern becomes RoutePatternComponents (Omit<URLPatternInit, 'pathname'>):
the type omits pathname and the constructor rejects it at runtime for
JS callers, so a record can never fork pathname identity between route
metadata and the matcher. Full-URL components (hostname/protocol/…) are
unaffected; Framework Mode records never carried a second pathname.
router.searchParams returned the router's live internal URLSearchParams;
a loader/action (or any reader) calling .set() would rewrite canonical
router state without touching the address bar. The getter now returns a
fresh copy per read, so loader and action contexts each get their own
mutable copy. Tests: getter isolation (state, address bar, subsequent
navigations) and a loader mutating its copy without polluting the router.
Audit of all consumers (version anchors, docs truth, strategic docs,
release state) shows only channel classification reads it; full checkpoint
identity already flows through identifiers/compareVersions/next helpers.
The field comment now says so explicitly.
The supplemental review job is non-blocking; missing/errored reviews are
detected and reported as warnings, never counted as evidence. VERSION_PLAN,
ADR-0152 and the issue map previously demanded a fail-closed merge
prerequisite; all three now state one policy.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

…tePatternComponents

The RouteRecord.pattern type narrowing drifts the public shape hash and
generated API reference; both artifacts are regenerated, not hand-edited.
Also drop the provider name from VERSION_PLAN (role-neutral docs gate).
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant